home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / c / cxref-1.001 / cxref-1~ / cxref / xref.c < prev   
Encoding:
C/C++ Source or Header  |  1996-02-24  |  19.2 KB  |  708 lines

  1. /***************************************
  2.   $Header: /home/amb/cxref/RCS/xref.c 1.11 1996/02/24 14:54:19 amb Exp $
  3.  
  4.   C Cross Referencing & Documentation tool. Version 1.0
  5.  
  6.   Cross referencing of functions.
  7.   ******************/ /******************
  8.   Written by Andrew M. Bishop
  9.  
  10.   This file Copyright 1995,96 Andrew M. Bishop
  11.   It may be distributed under the GNU Public License, version 2, or
  12.   any higher version.  See section COPYING of the GNU Public license
  13.   for conditions under which this file may be redistributed.
  14.   ***************************************/
  15.  
  16. /*+ The names of the function cross reference files. +*/
  17. #define XREF_FUNC_FILE   ".function"
  18. #define XREF_FUNC_BACKUP ".function~"
  19.  
  20. /*+ The names of the variable cross reference files. +*/
  21. #define XREF_VAR_FILE    ".variable"
  22. #define XREF_VAR_BACKUP  ".variable~"
  23.  
  24. /*+ The names of the include cross reference files. +*/
  25. #define XREF_INC_FILE    ".include"
  26. #define XREF_INC_BACKUP  ".include~"
  27.  
  28. /*+ The names of the type cross reference files. +*/
  29. #define XREF_TYPE_FILE   ".typedef"
  30. #define XREF_TYPE_BACKUP ".typedef~"
  31.  
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <unistd.h>
  36.  
  37. #include "memory.h"
  38. #include "datatype.h"
  39. #include "cxref.h"
  40.  
  41. /*+ The name of the directory for the output. +*/
  42. extern char* option_odir;
  43.  
  44. /*+ The base name of the file for the output. +*/
  45. extern char* option_name;
  46.  
  47. /*+ The option for cross referencing. +*/
  48. extern int option_xref;
  49.  
  50. /*+ The option for indexing. +*/
  51. extern int option_index;
  52.  
  53. static void check_for_called(File file,char* called,char* caller,char* filename);
  54. static void check_for_caller(File file,char* called,char* filename);
  55. static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname);
  56. static int  check_for_var_func(File file,Variable var,Function func);
  57. static void fixup_extern_var(Variable var,StringList* refs);
  58.  
  59. /*++++++++++++++++++++++++++++++++++++++
  60.   Cross reference the functions, variables and includes that are used in this file
  61.   with the global functions, variables and includes. The types that are defined are also listed here.
  62.  
  63.   File file The file structure containing the information.
  64.   ++++++++++++++++++++++++++++++++++++++*/
  65.  
  66. void CrossReference(File file)
  67. {
  68.  FILE *in,*out;
  69.  char *ifile,*ofile;
  70.  
  71.  
  72.  /* Format: filename [[%]include1] [[%]include2] ... : Files include1, include2, ... are included in filename;
  73.     those with a % are local. */
  74.  
  75.  if(option_xref&XREF_FILE) /* First do the files */
  76.    {
  77.     Include inc;
  78.  
  79.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
  80.     ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_BACKUP);
  81.  
  82.     in =fopen(ifile,"r");
  83.     out=fopen(ofile,"w");
  84.  
  85.     if(!out)
  86.       {fprintf(stderr,"cxref: Failed to open the include cross reference file '%s'\n",ofile);exit(1);}
  87.  
  88.     fprintf(out,"%s",file->name);
  89.     for(inc=file->includes;inc;inc=inc->next)
  90.        fprintf(out," %s%s",inc->scope==LOCAL?"%":"",inc->name);
  91.     fprintf(out,"\n");
  92.  
  93.     if(in)
  94.       {
  95.        char include[128],filename[128],ch;
  96.  
  97.        while(fscanf(in,"%s%c",filename,&ch)==2)
  98.          {
  99.           int diff_file=strcmp(filename,file->name);
  100.  
  101.           if(diff_file)
  102.              fprintf(out,"%s",filename);
  103.  
  104.           while(ch==' ')
  105.             {
  106.              fscanf(in,"%s%c",include,&ch);
  107.  
  108.              if(diff_file)
  109.                 fprintf(out," %s",include);
  110.  
  111.              if(include[0]=='%' && !strcmp(&include[1],file->name))
  112.                 AddToStringList(&file->inc_in,filename,1);
  113.             }
  114.  
  115.           if(diff_file)
  116.              fprintf(out,"\n");
  117.          }
  118.  
  119.        fclose(in);
  120.        unlink(ifile);
  121.       }
  122.  
  123.     fclose(out);
  124.     rename(ofile,ifile);
  125.    }
  126.  
  127.  /* Format: filename funcname scope [[%][&]funcname1] [[%][&]funcname2] ... : The function funcname in file filename
  128.     calls or references functions funcname1, funcname2 ... ; those with a % are local, with a & are references. */
  129.  /* Format: filename $ 0 [[%]&funcname1] [[%]&funcname2] ... : The file references functions funcname1, funcname2 ... ;
  130.     those with a % are local.  */
  131.  
  132.  if(option_xref&XREF_FUNC) /* Now do the functions */
  133.    {
  134.     Function func;
  135.     int i;
  136.  
  137.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
  138.     ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_BACKUP);
  139.  
  140.     in =fopen(ifile,"r");
  141.     out=fopen(ofile,"w");
  142.  
  143.     if(!out)
  144.       {fprintf(stderr,"cxref: Failed to open the functional cross reference file '%s'\n",ofile);exit(1);}
  145.  
  146.     for(i=0;i<file->f_refs.n;i++)
  147.        check_for_called(file,ConcatStrings(2,"&",file->f_refs.s[i]),NULL,file->name);
  148.  
  149.     for(func=file->functions;func;func=func->next)
  150.       {
  151.        for(i=0;i<func->calls.n;i++)
  152.           check_for_called(file,func->calls.s[i],func->name,file->name);
  153.        for(i=0;i<func->f_refs.n;i++)
  154.           check_for_called(file,ConcatStrings(2,"&",func->f_refs.s[i]),func->name,file->name);
  155.       }
  156.  
  157.     for(func=file->functions;func;func=func->next)
  158.        check_for_caller(file,func->name,file->name);
  159.  
  160.     if(file->f_refs.n)
  161.       {
  162.        fprintf(out,"%s $ 0",file->name);
  163.        for(i=0;i<file->f_refs.n;i++)
  164.          {
  165.           char* temp=strchr(file->f_refs.s[i],':');
  166.           if(temp)
  167.             {
  168.              temp[-1]=0;
  169.              fprintf(out," %%&%s",file->f_refs.s[i]);
  170.              temp[-1]=' ';
  171.             }
  172.           else
  173.              fprintf(out," &%s",file->f_refs.s[i]);
  174.          }
  175.        fprintf(out,"\n");
  176.       }
  177.  
  178.     for(func=file->functions;func;func=func->next)
  179.       {
  180.        fprintf(out,"%s %s %d",file->name,func->name,func->scope);
  181.        for(i=0;i<func->calls.n;i++)
  182.          {
  183.           char* temp=strchr(func->calls.s[i],':');
  184.           if(temp)
  185.             {
  186.              temp[-1]=0;
  187.              fprintf(out," %%%s",func->calls.s[i]);
  188.              temp[-1]=' ';
  189.             }
  190.           else
  191.              fprintf(out," %s",func->calls.s[i]);
  192.          }
  193.        for(i=0;i<func->f_refs.n;i++)
  194.          {
  195.           char* temp=strchr(func->f_refs.s[i],':');
  196.           if(temp)
  197.             {
  198.              temp[-1]=0;
  199.              fprintf(out," %%&%s",func->f_refs.s[i]);
  200.              temp[-1]=' ';
  201.             }
  202.           else
  203.              fprintf(out," &%s",func->f_refs.s[i]);
  204.          }
  205.        fprintf(out,"\n");
  206.       }
  207.  
  208.     if(in)
  209.       {
  210.        char ch,funcname[64],filename[128],called[64];
  211.        int scope;
  212.  
  213.        while(fscanf(in,"%s %s %d%c",filename,funcname,&scope,&ch)==4)
  214.          {
  215.           int diff_file=strcmp(filename,file->name);
  216.  
  217.           if(diff_file)
  218.             {
  219.              if(funcname[0]!='$')
  220.                 check_for_caller(file,funcname,filename);
  221.              fprintf(out,"%s %s %d",filename,funcname,scope);
  222.             }
  223.  
  224.           while(ch==' ')
  225.             {
  226.              fscanf(in,"%s%c",called,&ch);
  227.              if(diff_file)
  228.                {
  229.                 if(called[0]!='%')
  230.                    check_for_called(file,called,funcname,filename);
  231.                 fprintf(out," %s",called);
  232.                }
  233.             }
  234.           if(diff_file)
  235.              fprintf(out,"\n");
  236.          }
  237.  
  238.        fclose(in);
  239.        unlink(ifile);
  240.       }
  241.  
  242.     fclose(out);
  243.     rename(ofile,ifile);
  244.    }
  245.  
  246.  /* Format: filename varname scope [$] [[%]funcname1] [[%]funcname2] ... : variable varname is used in
  247.     the file filename if $, and functions funcname1, funcname2 ... Those with a % are local.  */
  248.  
  249.  if(option_xref&XREF_VAR) /* Now do the variables */
  250.    {
  251.     Variable var;
  252.     Function func;
  253.  
  254.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
  255.     ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_BACKUP);
  256.  
  257.     in =fopen(ifile,"r");
  258.     out=fopen(ofile,"w");
  259.  
  260.     if(!out)
  261.       {fprintf(stderr,"cxref: Failed to open the variable cross reference file '%s'\n",ofile);exit(1);}
  262.  
  263.     for(var=file->variables;var;var=var->next)
  264.       {
  265.        check_for_var(file,var->name,file->name,var->scope,NULL);
  266.        fprintf(out,"%s %s %d",file->name,var->name,var->scope);
  267.        if(check_for_var_func(file,var,NULL))
  268.           fprintf(out," $");
  269.        for(func=file->functions;func;func=func->next)
  270.           if(check_for_var_func(file,var,func))
  271.              fprintf(out," %s%s",func->scope==LOCAL?"%":"",func->name);
  272.        fprintf(out,"\n");
  273.       }
  274.  
  275.     if(in)
  276.       {
  277.        char varname[64],filename[128],funcname[64],ch;
  278.        int scope;
  279.  
  280.        while(fscanf(in,"%s %s %d%c",filename,varname,&scope,&ch)==4)
  281.          {
  282.           int diff_file=strcmp(filename,file->name);
  283.  
  284.           if(diff_file)
  285.             {
  286.              if(!(scope&LOCAL))
  287.                 check_for_var(file,varname,filename,scope,NULL);
  288.              fprintf(out,"%s %s %d",filename,varname,scope);
  289.             }
  290.  
  291.           while(ch==' ')
  292.             {
  293.              fscanf(in,"%s%c",funcname,&ch);
  294.  
  295.              if(diff_file)
  296.                {
  297.                 if(!(scope&LOCAL))
  298.                    if(funcname[0]=='%')
  299.                       check_for_var(file,varname,filename,scope,&funcname[1]);
  300.                    else
  301.                       check_for_var(file,varname,filename,scope,funcname);
  302.                 fprintf(out," %s",funcname);
  303.                }
  304.             }
  305.  
  306.           if(diff_file)
  307.              fprintf(out,"\n");
  308.          }
  309.  
  310.        fclose(in);
  311.        unlink(ifile);
  312.       }
  313.  
  314.     /* We must fix the location of the extern variables now since it was not known earlier. */
  315.  
  316.     fixup_extern_var(file->variables,&file->v_refs);
  317.     for(func=file->functions;func;func=func->next)
  318.        fixup_extern_var(file->variables,&func->v_refs);
  319.  
  320.     fclose(out);
  321.     rename(ofile,ifile);
  322.    }
  323.  
  324.  /* Format: filename typename type... : For a typedef type.     */
  325.  /* Format: filename #        type... : For a non typedef type. */
  326.  
  327.  if(option_xref&XREF_TYPE) /* Now do the types */
  328.    {
  329.     Typedef type;
  330.  
  331.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
  332.     ofile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_BACKUP);
  333.  
  334.     in =fopen(ifile,"r");
  335.     out=fopen(ofile,"w");
  336.  
  337.     if(!out)
  338.       {fprintf(stderr,"cxref: Failed to open the typedef reference file '%s'\n",ofile);exit(1);}
  339.  
  340.     for(type=file->typedefs;type;type=type->next)
  341.        if(type->type)
  342.           fprintf(out,"%s %s %s\n",file->name,type->name,type->type);
  343.        else
  344.           fprintf(out,"%s # %s\n",file->name,type->name);
  345.  
  346.     if(in)
  347.       {
  348.        char typename[128],filename[128];
  349.  
  350.        while(fscanf(in,"%s %s",filename,typename)==2)
  351.          {
  352.           int diff_file=strcmp(filename,file->name);
  353.  
  354.           if(diff_file)
  355.              fprintf(out,"%s %s",filename,typename);
  356.  
  357.           fgets(typename,128,in);
  358.  
  359.           if(diff_file)
  360.              fputs(typename,out);
  361.          }
  362.  
  363.        fclose(in);
  364.        unlink(ifile);
  365.       }
  366.  
  367.     fclose(out);
  368.     rename(ofile,ifile);
  369.    }
  370. }
  371.  
  372.  
  373. /*++++++++++++++++++++++++++++++++++++++
  374.   Create the appendix of files, global functions, global variables and types.
  375.  
  376.   StringList* files The list of files to create.
  377.  
  378.   StringList* funcs The list of functions to create.
  379.  
  380.   StringList* vars The list of variables to create.
  381.  
  382.   StringList* types The list of types to create.
  383.   ++++++++++++++++++++++++++++++++++++++*/
  384.  
  385. void CreateAppendix(StringList* files,StringList* funcs,StringList* vars,StringList* types)
  386. {
  387.  FILE *in;
  388.  char *ifile;
  389.  
  390.  if(option_index&INDEX_FILE) /* First do the files */
  391.    {
  392.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_INC_FILE);
  393.  
  394.     in =fopen(ifile,"r");
  395.  
  396.     if(in)
  397.       {
  398.        char include[128],filename[128],ch;
  399.  
  400.        while(fscanf(in,"%s%c",filename,&ch)==2)
  401.          {
  402.           AddToStringList(files,filename,1);
  403.           while(ch==' ')
  404.              fscanf(in,"%s%c",include,&ch);
  405.          }
  406.  
  407.        fclose(in);
  408.       }
  409.    }
  410.  
  411.  if(option_index&INDEX_FUNC) /* Now do the functions */
  412.    {
  413.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_FUNC_FILE);
  414.  
  415.     in =fopen(ifile,"r");
  416.  
  417.     if(in)
  418.       {
  419.        char ch,caller[64],filename[128],called[64];
  420.        int scope;
  421.  
  422.        while(fscanf(in,"%s %s %d%c",filename,caller,&scope,&ch)==4)
  423.          {
  424.           if(scope&GLOBAL)
  425.              AddToStringList(funcs,ConcatStrings(3,caller," : ",filename),1);
  426.           while(ch==' ')
  427.              fscanf(in,"%s%c",called,&ch);
  428.          }
  429.  
  430.        fclose(in);
  431.       }
  432.    }
  433.  
  434.  if(option_index&INDEX_VAR) /* Now do the variables */
  435.    {
  436.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_VAR_FILE);
  437.  
  438.     in =fopen(ifile,"r");
  439.  
  440.     if(in)
  441.       {
  442.        char variable[64],filename[128],funcname[64],ch;
  443.        int scope;
  444.  
  445.        while(fscanf(in,"%s %s %d%c",filename,variable,&scope,&ch)==4)
  446.          {
  447.           if(scope&GLOBAL)
  448.              AddToStringList(vars,ConcatStrings(3,variable," : ",filename),1);
  449.           while(ch==' ')
  450.              fscanf(in,"%s%c",funcname,&ch);
  451.          }
  452.  
  453.        fclose(in);
  454.       }
  455.    }
  456.  
  457.  if(option_index&INDEX_TYPE) /* Now do the types */
  458.    {
  459.     ifile=ConcatStrings(4,option_odir,"/",option_name,XREF_TYPE_FILE);
  460.  
  461.     in =fopen(ifile,"r");
  462.  
  463.     if(in)
  464.       {
  465.        char typename[128],filename[128];
  466.  
  467.        while(fscanf(in,"%s %s",filename,typename)==2)
  468.          {
  469.           if(typename[0]=='#')
  470.             {
  471.              fgets(typename,128,in);
  472.              typename[strlen(typename)-1]=0;
  473.              AddToStringList(types,ConcatStrings(3,&typename[1]," : ",filename),1);
  474.             }
  475.           else
  476.             {
  477.              AddToStringList(types,ConcatStrings(3,typename," : ",filename),1);
  478.              fgets(typename,128,in);
  479.             }
  480.          }
  481.  
  482.        fclose(in);
  483.       }
  484.    }
  485.  
  486. }
  487.  
  488. /*++++++++++++++++++++++++++++++++++++++
  489.   Check through all of the functions in this file to see if any of them are called or referenced.
  490.  
  491.   File file The file structure.
  492.  
  493.   char* called The function that is called.
  494.  
  495.   char* caller The function that the called function is called from.
  496.  
  497.   char* filename The file that the function is called from.
  498.   ++++++++++++++++++++++++++++++++++++++*/
  499.  
  500. static void check_for_called(File file,char* called,char* caller,char* filename)
  501. {
  502.  Function func;
  503.  
  504.  /* Check for function calls */
  505.  
  506.  if(called[0]!='&')
  507.     for(func=file->functions;func;func=func->next)
  508.       {
  509.        if(!strcmp(called,func->name))
  510.           AddToStringList(&func->called,ConcatStrings(3,caller," : ",filename),1);
  511.       }
  512.  
  513.  /* Check for function references */
  514.  
  515.  else
  516.     for(func=file->functions;func;func=func->next)
  517.       {
  518.        if(!strcmp(&called[1],func->name))
  519.          {
  520.           char* used_in;
  521.  
  522.           if(caller)
  523.              used_in=ConcatStrings(3,caller," : ",filename);
  524.           else
  525.              used_in=ConcatStrings(2,"$",filename);
  526.  
  527.           AddToStringList(&func->used,used_in,1);
  528.          }
  529.       }
  530. }
  531.  
  532.  
  533. /*++++++++++++++++++++++++++++++++++++++
  534.   Check through all of the functions in this file to see if any of them are callers or referencers.
  535.  
  536.   File file The file structure.
  537.  
  538.   char* called The function that is called.
  539.  
  540.   char* filename The file that the called function is in.
  541.   ++++++++++++++++++++++++++++++++++++++*/
  542.  
  543. static void check_for_caller(File file,char* called,char* filename)
  544. {
  545.  int i;
  546.  Function func;
  547.  
  548.  /* Check the functions that are called. */
  549.  
  550.  for(func=file->functions;func;func=func->next)
  551.    {
  552.     for(i=0;i<func->calls.n;i++)
  553.        if(!strcmp(called,func->calls.s[i]))
  554.          {
  555.           char* old=func->calls.s[i];
  556.           func->calls.s[i]=MallocString(ConcatStrings(3,func->calls.s[i]," : ",filename));
  557.           Free(old);
  558.          }
  559.    }
  560.  
  561.  /* Check the functions that are referenced. */
  562.  
  563.  for(i=0;i<file->f_refs.n;i++)
  564.     if(!strcmp(called,file->f_refs.s[i]))
  565.       {
  566.        char* old=file->f_refs.s[i];
  567.        file->f_refs.s[i]=MallocString(ConcatStrings(3,file->f_refs.s[i]," : ",filename));
  568.        Free(old);
  569.       }
  570.  
  571.  for(func=file->functions;func;func=func->next)
  572.    {
  573.     for(i=0;i<func->f_refs.n;i++)
  574.        if(!strcmp(called,func->f_refs.s[i]))
  575.          {
  576.           char* old=func->f_refs.s[i];
  577.           func->f_refs.s[i]=MallocString(ConcatStrings(3,func->f_refs.s[i]," : ",filename));
  578.           Free(old);
  579.          }
  580.    }
  581.  
  582. }
  583.  
  584.  
  585. /*++++++++++++++++++++++++++++++++++++++
  586.   Check through all of the variables in this file to see if any of them are extern usage of others.
  587.  
  588.   File file The file structure.
  589.  
  590.   char* variable The global variable name.
  591.  
  592.   char* filename The file that the variable is used in.
  593.  
  594.   int scope The scope of the variable in the foreign file.
  595.  
  596.   char* funcname The name of a function that uses the variable.
  597.   ++++++++++++++++++++++++++++++++++++++*/
  598.  
  599. static void check_for_var(File file,char* variable,char* filename,int scope,char* funcname)
  600. {
  601.  Variable var;
  602.  
  603.  for(var=file->variables;var;var=var->next)
  604.     if(!strcmp(variable,var->name))
  605.       {
  606.        if(!funcname)
  607.          {
  608.           if(scope&GLOBAL && var->scope&(EXTERNAL|EXTERN_H))
  609.              var->defined=MallocString(filename);
  610.  
  611.           if(scope&(GLOBAL|EXTERNAL|EXTERN_H) && var->scope&GLOBAL)
  612.              AddToStringList(&var->visible,filename,1);
  613.          }
  614.        else
  615.           if(!strcmp(funcname,filename))
  616.              AddToStringList(&var->used,ConcatStrings(2,"$",filename),1);
  617.           else
  618.              AddToStringList(&var->used,ConcatStrings(3,funcname," : ",filename),1);
  619.       }
  620. }
  621.  
  622.  
  623. /*++++++++++++++++++++++++++++++++++++++
  624.   Check through the function to see if it uses the variable, if func is NULL then check the file.
  625.  
  626.   int check_for_var_func Returns 1 if the variable is referenced from the function or file.
  627.  
  628.   File file The file that the function belongs to.
  629.  
  630.   Variable var The variable that may be referenced.
  631.  
  632.   Function func The function that is to be checked.
  633.   ++++++++++++++++++++++++++++++++++++++*/
  634.  
  635. static int check_for_var_func(File file,Variable var,Function func)
  636. {
  637.  int i;
  638.  
  639.  if(func)
  640.    {
  641.     for(i=0;i<func->v_refs.n;i++)
  642.        if(!strcmp(var->name,func->v_refs.s[i]))
  643.          {
  644.           char* old=func->v_refs.s[i];
  645.           AddToStringList(&var->used,ConcatStrings(3,func->name," : ",file->name),1);
  646.           if(var->scope&(GLOBAL|LOCAL))
  647.              func->v_refs.s[i]=MallocString(ConcatStrings(3,old," : ",file->name));
  648.           else
  649.              func->v_refs.s[i]=MallocString(ConcatStrings(2,old," : $"));
  650.           Free(old);
  651.           return(1);
  652.          }
  653.    }
  654.  else
  655.    {
  656.     for(i=0;i<file->v_refs.n;i++)
  657.        if(!strcmp(var->name,file->v_refs.s[i]))
  658.          {
  659.           char* old=file->v_refs.s[i];
  660.           AddToStringList(&var->used,ConcatStrings(2,"$",file->name),1);
  661.           if(var->scope&(GLOBAL|LOCAL))
  662.              file->v_refs.s[i]=MallocString(ConcatStrings(3,old," : ",file->name));
  663.           else
  664.              file->v_refs.s[i]=MallocString(ConcatStrings(2,old," : $"));
  665.           Free(old);
  666.           return(1);
  667.          }
  668.    }
  669.  
  670.  return(0);
  671. }
  672.  
  673.  
  674. /*++++++++++++++++++++++++++++++++++++++
  675.   We can only now put in the location of the external variables that we found were used.
  676.   Previously we did not know the location of their global definition.
  677.  
  678.   Variable var The list of variables for this file.
  679.  
  680.   StringList* refs A list of variable references from a file or a function.
  681.   ++++++++++++++++++++++++++++++++++++++*/
  682.  
  683. static void fixup_extern_var(Variable var,StringList* refs)
  684. {
  685.  int i;
  686.  Variable v;
  687.  
  688.  for(i=0;i<refs->n;i++)
  689.    {
  690.     char* old=refs->s[i];
  691.     if(strstr(old,": $"))
  692.        for(v=var;v;v=v->next)
  693.           if(v->scope&(EXTERNAL|EXTERN_H) && !strncmp(old,v->name,strlen(v->name)))
  694.             {
  695.              if(v->defined)
  696.                {
  697.                 old[strlen(old)-1]=0;
  698.                 refs->s[i]=MallocString(ConcatStrings(2,old,v->defined));
  699.                }
  700.              else
  701.                 refs->s[i]=MallocString(v->name);
  702.  
  703.              Free(old);
  704.              break;
  705.             }
  706.    }
  707. }
  708.